using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace OpenRay
{
	//Immutable class
	public class PhongMaterial : Material
	{
		private readonly List<Color> ambient = new List<Color>(2);
		private readonly List<Color> diffuse = new List<Color>(2);
		private readonly List<Color> specular = new List<Color>(2);
		private readonly List<Color> emissive = new List<Color>(2);
		private readonly List<float> shininess = new List<float>(2);
		
		public PhongMaterial ( IList<Color> a, IList<Color> d, IList<Color> s, IList<Color> e, IList<float> sh )
		{	
			Debug.Assert( a.Count == 2, "Incorrect size of ambient term provided" );
			Debug.Assert( d.Count == 2, "Incorrect size of diffuse term provided" );
			Debug.Assert( s.Count == 2, "Incorrect size of specular term provided");
			Debug.Assert( e.Count == 2, "Incorrect size of emissive term provided" );
			Debug.Assert( sh.Count == 2, "Incorrect size of shininess term provided" );
			
			ambient.AddRange( a );
			diffuse.AddRange( d );
			specular.AddRange( s );
			emissive.AddRange( e );
			shininess.AddRange( sh );
		}
		
		protected Color PhongMaterialShade( Point worldHit, Point modelHit, Vector normalizedViewer, Vector surfaceNormal, IList<Light> lights, Material.Face f )
		{
			Debug.Assert( normalizedViewer.IsNormal() );
			
			Vector reversedNormalizedViewer = -normalizedViewer;
			
			int index = (int)f;
			Color ret = emissive[index].Evaluate(modelHit);
			
			foreach( PhongLight l in lights ) {
				ret += l.ComputeLighting( ambient[index],
				                          diffuse[index],
				                          specular[index], 
				                          shininess[index],
				                          worldHit, reversedNormalizedViewer, surfaceNormal );
			}
			
			return ret;
		}
		
		public override Color Shade( Point worldHit, Point ModelHit, Vector normalizedViewer, Vector surfaceNormal, IList<Light> lights, uint depth ) {
			Material.Face f = FaceHit(normalizedViewer, surfaceNormal);
			
			return PhongMaterialShade( worldHit, ModelHit, normalizedViewer, surfaceNormal, lights, f );
		}
		
		public override Color Shade( Point worldHit, Point ModelHit, Vector normalizedViewer, Vector surfaceNormal, IList<Light> lights, Material.Face f, uint depth ) {			
			return PhongMaterialShade( worldHit, ModelHit, normalizedViewer, surfaceNormal, lights, f );
		}
	}
}

